package com.smart.lx.proxy.jdk;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 功能描述: <br>
 * 〈jdk动态代理〉
 *
 * @since: 1.0.0
 * @Author:abc
 * @Date: 2019/4/5
 * * Jdk Proxy特点:
 * 	1. 采用字节重组方式生产代理类, 实现动态代理;
 * 	2. 目标类必须实现接口;
 *
 * * jdk Proxy生产代理类过程:
 * 	1. 生产代理对象的方法: Proxy.newInstance(Class<?> [] classes,InovcationHandler handler);
 * 		* classes: target实现的所有接口;
 * 		* handler:
 * 			* 持有增强方法invoke(Object proxy, Method method, Object[] args);
 * 			* 持有被代理对象;
 * 	2. 校验是否需要动态生成proxy的class
 * 		* 根据classes和handler;
 * 		* 如果不需要动态生成, 则不执行3,4,5步;
 * 	3. 动态编写java代码;
 * 		* 新类持有handler的引用, 且构造器赋值;
 * 		* 新类实现所有cleasses;
 * 			* 所有实现的方法体, 都是handler的增强方法invoke(Object proxy, Method method, Object[] args);
 * 	4. 动态生成字节码文件;
 * 	5. 动态加载字节码文件;
 * 	6. 创建proxy对象:
 * 		* 注入handler;
 *
 * * 代理方法调用目标对象方法:
 * 	* Object obj = method.invoke(this.obj, args);
 * 	* 采用反射技术执行目标对象方法;

 */
public class ProxyForJdk implements InvocationHandler {

    private Object obj;//目标对象
    public Object getInstance(Object obj){
        this.obj = obj;
        Class clazz = obj.getClass();
        ClassLoader classLoader = clazz.getClassLoader();
        Class [] interfaces = clazz.getInterfaces();
        Object objr = Proxy.newProxyInstance(classLoader, interfaces, this);
        return objr;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before();
        Object obj = method.invoke(this.obj, args);
        System.out.println("编写代码");
        return obj;
    }



    public void before(){
        System.out.println("find source url");
    }

}

   /*//private static Class<?> getProxyClass0(ClassLoader loader,
                                           Class<?>... interfaces) {
//接口数不得超过65535个
   接口数不得超过65535个

        if (interfaces.length > 65535) {
            throw new IllegalArgumentException("interface limit exceeded");
        }
//代理类缓存，如果缓存中有代理类了直接返回，否则将由ProxyClassFactory创建代理类
        return proxyClassCache.get(loader, interfaces); */


